package com.pvdnc.riru.system_server;

import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;

import com.pvdnc.riru.ContextUtils;
import com.pvdnc.riru.GlobalProperties;
import com.pvdnc.riru.MethodUtils;
import com.pvdnc.riru.system_server.filter.PackageFilterManager;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

import andhook.lib.xposed.XC_MethodHook;
import andhook.lib.xposed.XposedBridge;

public class HookActivityManagerService  {
    private static final String TAG=HookActivityManagerService.class.getSimpleName();

    public HookActivityManagerService(ClassLoader cl){
        AMSUtils.systemReady(cl);
    }

    public void hookAll(){
        try {
            hookAddAppLocked();
            hookFinishBooting();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static final String ACTION_RA_BOOT_COMPLETED="riru.android.intent.action.BOOT_COMPLETED";

    private void hookFinishBooting() throws Exception {
        Class<?> amsClass=AMSUtils.get().getAMSClass();
        Method method=MethodUtils.getMethodByName(amsClass,"finishBooting").get(0);
        XposedBridge.hookMethod(method,new XC_MethodHook(){
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                try {
                    Log.d(TAG,"after invoke finishBooting");
                    //发送自定义启动完成广播
                    Intent intent = new Intent(ACTION_RA_BOOT_COMPLETED);
                    intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
                    Context context=ContextUtils.get();
                    Objects.requireNonNull(context);
                    context.sendBroadcast(intent);
                    Log.d(TAG,"finish sending broadcast:RA_BOOT_COMPLETED");
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        Log.d(TAG,"finish hooking finishBooting");
    }

    private void hookAddAppLocked() throws Exception {
        if(!GlobalProperties.PERSISTENT_HOOK_AVAILABLE)
            return;
        Class<?> amsClass=AMSUtils.get().getAMSClass();
        List<Method> methodList= MethodUtils.getMethodByName(amsClass,"addAppLocked");
        Log.d(TAG,"found addAppLocked count:"+methodList.size());
        Method halMethod=methodList.get(0);
        if(methodList.size()>1){//API>23，比如API>=28有两个不同的addAppLocked，实际做事的是参数多的那个
            int maxParamCount=0;
            for(Method method:methodList){
                int paramCount=method.getParameterTypes().length;
                if(paramCount<maxParamCount)
                    continue;
                maxParamCount=paramCount;
                halMethod=method;
            }
        }
        if(halMethod==null){
            Log.e(TAG,"fail to find appropriate addAppLocked to hook");
            return;
        }
        Log.d(TAG,"addAppLocked method:"+halMethod);
        XposedBridge.hookMethod(halMethod,new XC_MethodHook(){
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                try{
                    ApplicationInfo appInfo= (ApplicationInfo) param.args[0];
                    Log.d(TAG,"add app info:\n\t"+appInfo);
                    String pkgName=appInfo.packageName;
                    if(!PackageFilterManager.INSTANCE.callFilter(pkgName))
                        return;
                    //添加PERSISTENT标志位
                    Log.d(TAG,"attempt to make pkg:"+pkgName+" persistent");
                    appInfo.flags= AMSUtils.get().addPersistent(appInfo.flags);
                    //验证一下
                    if(AMSUtils.get().hasPersistent(appInfo.flags)){
                        Log.d(TAG,"pkg:"+pkgName+" has been already a persistent app");
                    }
                    //更新
                    param.args[0]=appInfo;
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        Log.d(TAG,"finish hooking addAppLocked");
    }
}
